import java.util.Arrays;
public class homework {

    //作业-------方法的创建和调用4.16
    public static int max(int a,int b){
        return a>b?a:b;
    }
    public static int max(int x,int y,int z){
        int max=max(x,y);
        return max(max,z);
    }
    public static double maxD(double a,double b){
        return a>b?a:b;
    }
    public static double maxD(double x,double y,double z){
        double max=maxD(x,y);
        return maxD(max,z);
    }
    public static int fac(int n){
        int ret=1;
        for(int i=1;i<=n;i++){
            ret*=i;
        }
        return ret;
    }
    public static int facSum(int n){
        int ret=1;
        int sum=0;
        for(int i=1;i<=n;i++){
            ret*=i;
            sum+=ret;
            //or sum+=fac(i);
        }
        return sum;
    }
    public static int fib(int n){
        if(n <= 2) {
            return 1;
        }
        else
            return fib(n-1) + fib(n-2);
    }
    public static int add(int a,int b){
        return a+b;
    }

    public static double add(double a,double b,double c){
        return a+b+c;
    }
    public static int fac2(int n){
        if(n==1)
            return 1;
        else
            return n*fac2(n-1);
    }
    public static void move(char pos1,char pos2){
        System.out.print(pos1+"->"+pos2+" ");
    }
    public static void hanNoTa(int n,char pos1,char pos2,char pos3){
        //pos1起始位置,pos2中转位置,pos3目标位置
        if(n==1)
            move(pos1,pos3);
        else{
            hanNoTa(n-1,pos1,pos3,pos2);
            //起始位置移动n-1个到中转位置
            move(pos1,pos3);//将剩下的在pos1上最大的一个移动到目标位置
            hanNoTa(n-1,pos2,pos1,pos3);
        }
    }



    //作业---------数组练习4.17
    public static void transform(int[] array){
        for(int i=0;i<array.length;i++){
            array[i]=array[i]*2;
        }
    }

    public static double avg(int[] array){
        double sum=0;
        for(int i=0;i<array.length;i++){
            sum+=array[i];
        }
        return sum*1.0/array.length;
    }
    public static void adjust(int[] array){
        int left=0;
        int right=array.length-1;
        while(left<right){
            while(left<right&&array[left]%2!=0){
                left++;
            }
            while(left<right&&array[right]%2==0){
                right--;
            }
            int tmp=array[left];
            array[left]=array[right];
            array[right]=tmp;
        }
    }

    public static void bubbleSort(int[] array) {
        //i代表的是趟数！！
        for (int i = 0; i < array.length - 1; i++) {
            //j代表每一趟比较的次数
            boolean flg = false;
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tmp;
                    flg = true;
                }
            }
            if (flg == false) {
                break;//说明有序了！！！
            }
        }
    }

    public static int[] func(int[] array,int key){
        for (int i = 0; i < array.length-1; i++) {
            for (int j = i+1; j < array.length; j++) {
                if(array[i]+array[j]==key){
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{-1,-1};
    }

    public static int find(int[] array){
        int ret=array[0];
        for(int i=1;i<array.length;i++){
            ret^=array[i];
            //a^a=0;  0^a=a; 这样就能找到只出现一次的数字了
        }
        return ret;
    }

    public static int func2(int[] array){
        Arrays.sort(array);
        return array[array.length/2];//先排序，如果给定的数组总是存在多数元素，那么中间元素就是多数元素
    }

    public static boolean func3(int[] array){
        int count=0;
        for (int i = 0; i <array.length ; i++) {
            if(array[i]%2!=0) {
                count++;
                if (count == 3)
                    return true;
            }
            else
                count=0;
        }
        return false;
    }

    public static void reverse(int[] array) {
        int left = 0;
        int right = array.length-1;
        while (left < right) {
            int tmp = array[left];
            array[left] = array[right];
            array[right] = tmp;
            left++;
            right--;
        }
    }



    //作业---------数组练习4.17
    public static void main(String[] args){
        //实现一个方法 transform, 以数组为参数, 循环将数组中的每个元素 乘以 2 ,
        // 并设置到对应的数组元素上. 例如 原数组为 {1, 2, 3}, 修改之后为 {2, 4, 6}
        int[] array={1,2,3};
        System.out.println(Arrays.toString(array));
        transform(array);
        System.out.println(Arrays.toString(array));

        //实现一个方法 avg, 以数组为参数, 求数组中所有元素的平均值(注意方法的返回值类型).
        int[] array1={3,4,6,7,8,9};
        double ret=avg(array1);
        System.out.println(ret);

        //调整数组顺序使得奇数位于偶数之前。调整之后，不关心大小顺序。=
        //如数组：[1,2,3,4,5,6]
        //调整后可能是：[1, 5, 3, 4, 2, 6]
        int[] array2={1,2,3,4,5,6};
        adjust(array2);
        System.out.println(Arrays.toString(array2));

        //给定一个整型数组, 实现冒泡排序(升序排序)
        int[] array3= {1,2,13,4,15};
        bubbleSort(array3);
        System.out.println(Arrays.toString(array3));

        //给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出 和为目标值 target 的那 两个 整数，并返回它们的数组下标。
        //你可以假设每种输入只会对应一个答案。但是，数组中同一个元素在答案里不能重复出现。
        //示例 1：
        //输入：nums = [2,7,11,15], target = 9
        //输出：[0,1]
        //解释：因为 nums[0] + nums[1] == 9 ，返回 [0, 1]
        int[] array4={2,7,11,15};
        int[] ret3=func(array4,22);
        System.out.println(Arrays.toString(ret3));

        //给定一个非空整数数组，除了某个元素只出现一次以外，
        // 其余每个元素均出现两次。找出那个只出现了一次的元素。
        int[] array5={4,1,2,1,2};
        int ret4=find(array5);
        System.out.println(ret4);

        //给定一个大小为 n 的数组，找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
        //你可以假设数组是非空的，并且给定的数组总是存在多数元素。
        int[] array6={2,2,1,1,1,2,2};
        int ret5=func2(array6);
        System.out.println(ret5);

        //给你一个整数数组 arr，请你判断数组中是否存在连续三个元素都是奇数的情况：
        // 如果存在，请返回 true ；否则，返回 false
        int[] array7={1,2,34,3,4,5,7,23,12};
        int[] array8={3,7,6,1};
        System.out.println(func3(array7));
        System.out.println(func3(array8));

        //数组逆置
        int[] array9 = {1,2,34,3,4,5,8,23,12};
        reverse(array9);
        System.out.println(Arrays.toString(array9));


    }




    //作业-------方法的创建和调用4.16
    public static void main1(String[] args) {
        //创建方法求两个数的最大值max2，随后再写一个求3个数的最大值的函数max3。
        //要求：在max3这个函数中，调用max2函数，来实现3个数的最大值计算
        int ret=max(20,8,9);
        System.out.println(ret);

        //求n的阶乘
        int ret2=fac(5);
        System.out.println(ret2);

        //求1！+2！+3！+4！+........+n!的和
        int ret3=facSum(5);
        System.out.println(ret3);

        //求斐波那契数列的第n项。(迭代实现)
        int ret4=fib(6);
        System.out.println(ret4);

        //在同一个类中,分别定义求两个整数的方法 和 三个小数之和的方法。 并执行代码，求出结果
        int ret5=add(5,6);
        double ret6=add(5.9,6.3,1.1);
        System.out.println(ret5);
        System.out.println(ret6);

        //在同一个类中定义多个方法：要求不仅可以求2个整数的最大值，还可以求3个小数的最大值？
        int ret7=max(76,99);
        double ret8=maxD(20.7,55.4,99.0);
        System.out.println(ret7);
        System.out.println(ret8);

        //递归求 N 的阶乘
        int ret9=fac2(5);
        System.out.println(ret9);

        //递归求解汉诺塔问题
        hanNoTa(1,'A','B','C');
        System.out.println();
        hanNoTa(2,'A','B','C');
        System.out.println();
        hanNoTa(3,'A','B','C');
        System.out.println();
        hanNoTa(4,'A','B','C');
    }
}